package com.ebt.m.customer.drawable;

import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;

public class RoundDrawable extends Drawable {

	private static final int COLORDRAWABLE_DIMENSION = 2;
	private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;

	private Bitmap mBitmap;
	private BitmapShader mBitmapShader;
	private Paint mPaintBitmap = new Paint();
	private RectF mRectBounds = new RectF();
	private final Matrix mShaderMatrix = new Matrix();

	private float mDiameter = 0;
	private float mRadius = 0;
	private int mBitmapWidth = 0;
	private int mBitmapHeight = 0;
	private int mShadowRadius = 4;
	private int mShadowX = 1;
	private int mShadowY = 4;
	private int mShadowColor = 0x55000000;

	public RoundDrawable(Bitmap bitmap) {
		mBitmap = bitmap;
		init();
	}

	public RoundDrawable(Drawable drawable) {
		mBitmap = getBitmapFromDrawable(drawable);
		init();
	}

	private void init(){
		mBitmapWidth = mBitmap.getWidth();
		mBitmapHeight = mBitmap.getHeight();
		mRadius = Math.min(mBitmapWidth, mBitmapHeight);
		mRectBounds.set(0, 0, mBitmapWidth, mBitmapHeight);
		mBitmapShader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);
		
		mPaintBitmap.setAntiAlias(true);
		mPaintBitmap.setDither(true);
		mPaintBitmap.setShader(mBitmapShader);
		
		setup();
	}
	
	@Override
	public void setBounds(int left, int top, int right, int bottom) {
		mDiameter = Math.min(right - left, bottom - top);
		super.setBounds(left, top, (int)(left + mDiameter), (int)(top + mDiameter));
		mRadius = mDiameter / 2;
		mRectBounds = new RectF(left, top, left + mDiameter, top + mDiameter);
		
		setup();
	}
	
	
	@Override
	public void draw(Canvas canvas) {
		canvas.drawCircle(mRectBounds.width() / 2.0f, mRectBounds.height() / 2.0f,
				mRadius - mShadowRadius * 3 / 2, mPaintBitmap);
	}

	@Override
	public int getIntrinsicWidth() {
		return mBitmap.getWidth();
	}

	@Override
	public int getIntrinsicHeight() {
		return mBitmap.getHeight();
	}

	@Override
	public void setAlpha(int alpha) {
        mPaintBitmap.setAlpha(alpha);
	}

	@Override
	public void setColorFilter(ColorFilter cf) {
        mPaintBitmap.setColorFilter(cf);
	}

	@Override
	public int getOpacity() {
		return PixelFormat.TRANSLUCENT;
	}

	public static Bitmap getBitmapFromDrawable(Drawable drawable) {
		if (drawable == null) {
			return null;
		}

		if (drawable instanceof BitmapDrawable) {
			return ((BitmapDrawable) drawable).getBitmap();
		}

		try {
			Bitmap bitmap;

			if (drawable instanceof ColorDrawable) {
				bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION,
						COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
			} else {
				bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
						drawable.getIntrinsicHeight(), BITMAP_CONFIG);
			}

			Canvas canvas = new Canvas(bitmap);
			drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
			drawable.draw(canvas);
			return bitmap;
		} catch (OutOfMemoryError e) {
			return null;
		}
	}
	
	private void setup() {
        if (mBitmap == null) {
        	invalidateSelf();
            return;
        }
        updateShaderMatrix();
        invalidateSelf();
    }

    private void updateShaderMatrix() {
        float scale;
        float dx = 0;
        float dy = 0;

        mShaderMatrix.set(null);
        if (mBitmapWidth > mBitmapHeight) {
            scale = mRectBounds.height() / (float) mBitmapHeight;
            dx = (mRectBounds.width() - mBitmapWidth * scale) * 0.5f;
        } else {
            scale = mRectBounds.width() / (float) mBitmapWidth;
            dy = (mRectBounds.height() - mBitmapHeight * scale) * 0.5f;
        }

        mShaderMatrix.setScale(scale, scale);
        mShaderMatrix.postTranslate((int) (dx + 0.5f) + mRectBounds.left, (int) (dy + 0.5f) + mRectBounds.top);
        mBitmapShader.setLocalMatrix(mShaderMatrix);
    }
}
